Canigó - Connector amb PICA
Connector amb la PICA
IntroduccióPropòsitEl propòsit del connector és proporcionar una interfície java per accedir a la PICA. El connector amb la PICA disposa de dos tipus de comunicació, un d'ells a través de web service síncron, i l'altre, mitjançant web service asíncron. Context i Escenaris d'ÚsEl connector PICA es troba dins els connectors de serveis funcional. Versions i DependènciesEn el present apartat es mostren quines són les versions i dependències necessàries per fer ús del Servei. Les dependències descrites a la següent url són requerides per tal de fer funcionar el servei: A l'incloure la dependència del connector en el projecte, podreu veure que s'afegeixen dues llibreries anomenades client-pica-2.3.2.jar i api-pica-2.3.2.jar. Aquestes llibreries són dependències directes del connector amb la PICA de Canigó i han estat desenvolupades per l'OT PICA. L'OT Canigó ha empaquetat aquestes llibreries i s'han publicat al repositori, dins el package canigo.connectors. Qualsevol dubte/consulta respecte funcionalitats, documentació, etc. d'aquestes llibreries, us podeu adreçar a l'OT PICA: oficinapica.ctti@gencat.cat A qui va dirigitAquest document va dirigit als següents perfils:
Documents i Fonts de Referència
Glossari
Descripció DetalladaArquitectura i ComponentsInterfícies i Components GenèricsEs pot trobar tota la documentació JavaDoc i el codi font referent aquests components a les següents urls: JavaDoc: http://canigo.ctti.gencat.net/confluence/canigodocs/site/canigo2_3_9/canigo-connectors-root/canigo-connectors-pica/apidocs/index.html RequerimentsEl connector amb la PICA de Canigó, ha estat desenvolupat amb Java 1.5, degut a requeriments tècnics que venien establerts. Per tant, es pot utilitzar el connector si s'està desenvolupant amb aquesta versió. En canvi, si s'està treballant amb versions anteriors, s'ha de realitzar la comunicació amb la PICA de forma directa. Per a més informació podeu adreçar-vos directament a l'Oficina Tècnica de la PICA (oficinapica.ctti@gencat.cat). Instal.lació i ConfiguracióInstal.lacióLa instal.lació del connector requereix de la utilització de la llibreria 'canigo-connectors-pica' i les dependències indicades a l'apartat 'Introducció-Versions i Dependències'. La instal.lació es realitza seguint el procediment habitual per components/serveis Canigó. És necessari tenir accés a la intranet de la Generalitat per poder fer proves i/o utilitzar-lo. Pel que fa a les dependències, n'hi ha dues que s'han de descarregar manualment:
Una alternativa és descarregar-se els artefactes i ubicar-los en els packages indicats, amb la particularitat que el axis2-ant-plugin, ha de tenir el nom: axis2-ant-plugin-1.3-maven-plugin.jar. ConfiguracióPrimer de tot, s'ha de crear una estructura de directoris a qualsevol ubicació dins el classpath del projecte, per exemple dins de "resources". L'estructura de directoris ha de ser com segueix:
Tot seguit mostrem gràficament l'estructura de directoris amb els fitxers inclosos:
És necessari un fitxer de configuració Spring a la pròpia aplicació, en el qual es defineixen les dades necessàries per a realitzar una correcta comunicació amb la PICA (requeridor, producte, configuració SSL -si s'escau-, etc.). Fitxer de configuració: picaServiceConfiguration.xml <beans> <bean name="ProducteModalitatBase" abstract="true" class="cat.gencat.pica.peticio.core.beans.ProducteModalitat"> <property name="passwordType" value="PasswordText"/> </bean> <bean id="requeridor" class="cat.gencat.pica.peticio.core.beans.Requeridor" singleton="true"> <property name="fitxerSignatura" value="signatura.properties"/> <property name="idSolicitante" value="ID_SOL"/> <property name="idTransmision" value="ID_TRANS"/> <property name="nombreSolicitante" value="SOL"/> <property name="password" value="PSW"/> <property name="user" value="USER"/> </bean> <bean id="PicaCanigoService" class="cat.gencat.testpica.prova.PicaServiceWrapper" singleton="false"> <!-- és requerit que s'indiqui aquest valor per axisDefinition --> <property name="axisDefinition" value="classpath:axis2client/" /> <!-- configuració SSL (opcional) --> <property name="trustStoreSSLKeystore" value="certificats/cert.jks" /> <property name="trustStoreSSLKeystoreType" value="JKS" /> <property name="trustStoreSSLKeystorePassword" value="password" /> <property name="loggingService" ref="loggingService"/> <property name="requeridor" ref="requeridor"/> <property name="modalitats"> <map> <entry key="KEY_MODALITAT"> <bean parent="ProducteModalitatBase"> <property name="signat" value="false"/> <property name="urlPICA" value="http://preproduccio.pica.gencat.intranet/ pica_cataleg/AppJava/services/PADRO_MUNICIPI_RESIDENCIA"/> <property name="codCertificado" value="COD_CERT"/> <property name="codProducto" value="COD_PRODUCTE"/> <property name="finalidad" value="FIN"/> <property name="nifEmisor" value="NNNNNNNNX"/> <property name="nombreEmisor" value="DEP. D'ACCIO SOCIAL I CIUTADANIA"/> </bean> </entry> </map> </property> </bean> <bean id="loggingConfigurator" class="net.gencat.ctti.canigo.services.logging.log4j.xml.HostDOMConfigurator" init-method="init"> <property name="configFileName"> <value>classpath:log4j-test.xml</value> </property> </bean> <bean id="loggingService" class="net.gencat.ctti.canigo.services.logging.log4j.Log4JServiceImpl" init-method="init"> <property name="configurator"> <ref local="loggingConfigurator" /> </property> </bean> </beans> Els beans definits en aquest fitxer són:
Els valors introduïts a cadascuna de les propietats dels beans han de correspondre amb les dades pertanyents al producte/modalitat que es vol consumir, dades de l'emissor, etc. L'únic valor requerit és el que es defineix per a la propietat de la definició d'Axis (dins el bean PicaCanigoService): <property name="axisDefinition" value="classpath:axis2client/"/>
D'altra banda, l'atribut fitxerSignatura del bean Requeridor, correspon a un fitxer de propietats que tindrà definides les dades del certificat: Fitxer de propietats: signatura.properties org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin #org.apache.ws.security.crypto.merlin.file=certificats.p12 #org.apache.ws.security.crypto.merlin.keystore.type=PKCS12 org.apache.ws.security.crypto.merlin.file=certificats.jks org.apache.ws.security.crypto.merlin.keystore.type=JKS org.apache.ws.security.crypto.merlin.keystore.password=CANIGO #org.apache.ws.security.crypto.merlin.keystore.provider=SunJSSE org.apache.ws.security.crypto.merlin.keystore.provider=SUN org.apache.ws.security.crypto.merlin.keystore.alias=CANIGO org.apache.ws.security.crypto.merlin.alias.password=CANIGO Finalment, cal incloure la dependència amb el connector a l'arxiu de configuració Maven2 del projecte (pom.xml): <dependency> <groupId>canigo.connectors</groupId> <artifactId>canigo-connectors-pica</artifactId> <version>2.3.2</version> </dependency> La versió de Canigó 2.3.2 és la primera en la qual es publica el connector amb la PICA, que correspon a la darrera release del framework. Per tant, a mida que es vagin publicant versions, s'haurà de modificar el nombre de versió indicat en el pom.xml. Utilització del ServeiFuncions PICALa utilització del Connector es basa principalment en la configuració. L'ús directe des dels clients es permet mitjançant la intefície del servei. Per utilitzar el servei PICA instanciarem un objecte IPicaServiceWrapper, cridant després a qualsevol dels mètodes que aquesta intefície presenta. IPicaServiceWrapper picaServiceWrapper = (IPicaServiceWrapper)beanFactory.getBean("PicaCanigoService"); assertNotNull(picaServiceWrapper); IPICAServiceSincron service = picaServiceWrapper.getPicaWebServiceSincronInstance("KEY_MODALITAT"); assertNotNull(service); On KEY_MODALITAT correspondrà a la clau del producte/modalitat definit en el map de modalitats que es troba al fitxer de configuració. Tot seguit, mostrarem les funcionalitats que incorpora aquesta interfície: public interface IPicaServiceWrapper { //obtenir les instancies de ws sincron/asincron public abstract IPICAServiceSincron getPicaWebServiceSincronInstance(String modalitat); public abstract IPICAServiceAsincron getPicaWebServiceAsincronInstance(String modalitat); //peticio al servei de la PICA per a ws sincron/asincron public abstract CridaSincronaResponseDocument ferPeticioAlServei(IPICAServiceSincron serviceSincron); public abstract CridaAsincronaResponseDocument ferPeticioAlServei(IPICAServiceAsincron serviceAsincron); //extreure les dades a partir de la resposta per a ws sincron/asincron public abstract List<DadesEspecifiques> extreuDadesEspecifiques(IPICAServiceSincron service, CridaSincronaResponseDocument resposta); public abstract List<DadesEspecifiques> extreuDadesEspecifiques(IPICAServiceAsincron service, ObtindreResultatResponseDocument resposta); //obtenir l'estat en que es troba la peticio (nomes ws asincron) public abstract EstatAsincron extreuEstatPeticio(IPICAServiceAsincron serviceAsincron, ObtindreResultatResponseDocument resposta); //obtenir resultat final de la peticio (nomes ws asincron) public abstract ObtindreResultatResponseDocument obtenirResultatPeticio(IPICAServiceAsincron serviceAsincron); } Exemple d'utilitzacióA continuació mostrem exemples d'ús de diferents les funcionalitats que ens proporciona la interfície, tant per a peticions síncrones com asíncrones.
public void testPicaServiceSincronWrapper() { try { IPicaServiceWrapper picaServiceWrapper = (IPicaServiceWrapper)beanFactory.getBean("PicaCanigoService"); assertNotNull(picaServiceWrapper); IPICAServiceSincron service = picaServiceWrapper.getPicaWebServiceSincronInstance("KEY_MODALITAT"); assertNotNull(picaServiceWrapper); //veure explicacio d'aquests metodes al final de l'exemple Funcionari func = creaFuncionari(); Titular tit = creaTitular(); List<DadesEspecifiques> datosEspecificosXML = createDadesEspecifiques(); service.setFuncionari( func ); service.setTitular( tit ); service.setDadesEspecifiques( datosEspecificosXML ); service.crearPeticio( "PROVA_OTCANIGO_" + System.currentTimeMillis() ); //fer peticio CridaSincronaResponseDocument resp = picaServiceWrapper.ferPeticioAlServei(service); //extreure resultat List<DadesEspecifiques> resposta= picaServiceWrapper.extreuDadesEspecifiques(service,resp); if (loggingService != null) { Iterator<DadesEspecifiques> it = resposta.iterator(); while (it.hasNext()) { DadesEspecifiques object = it.next(); loggingService.getLog(this.getClass()).info(object.getDadesXML()); } } } catch (Exception e) { if (loggingService != null) { loggingService.getLog(this.getClass()).error(e.getMessage()); } } finally { SSLConfiguration.resetSSL(); } }
public void testPicaServiceAsincronWrapper() { try { IPicaServiceWrapper picaServiceWrapper = (IPicaServiceWrapper) beanFactory.getBean("PicaCanigoService"); assertNotNull(picaServiceWrapper); IPICAServiceAsincron service = picaServiceWrapper.getPicaWebServiceAsincronInstance("KEY_MODALITAT"); assertNotNull(service); //veure explicacio d'aquests metodes al final de l'exemple Funcionari func = creaFuncionari(); Titular tit = creaTitular(); List<DadesEspecifiques> datosEspecificosXML = createDadesEspecifiques(); service.setFuncionari( func ); service.setTitular( tit ); service.setDadesEspecifiques( datosEspecificosXML ); service.crearPeticio( "OTCANIGO_" + System.currentTimeMillis() ); //fer la peticio al servei CridaAsincronaResponseDocument resp = picaServiceWrapper.ferPeticioAlServei(service); EstatAsincron estat = picaServiceWrapper.extreuEstatPeticio(service,resp); String codiEstat = estat.getCodiEstat(); int ter = estat.getTempsEstimatResposta(); if (loggingService != null) { loggingService.getLog(this.getClass()).info("TER: " + ter); loggingService.getLog(this.getClass()).info("Estat Petició:" + codiEstat); } if (codiEstat.equals("PeticioEnProces")) { Thread.sleep(new Long(estat.getTempsEstimatResposta()).longValue()*36000); }else { if (loggingService != null) { loggingService.getLog(this.getClass()).error("Codi estat peticio: " + codiEstat); loggingService.getLog(this.getClass()).error("Literal error: " + estat.getLiteralError()); } } //obtenir resultat peticio ObtindreResultatResponseDocument resultat = picaServiceWrapper.obtenirResultatPeticio(service); //extreure resultat peticio List<DadesEspecifiques> llistaResultat = picaServiceWrapper.extreuDadesEspecifiques(service,resultat); if (loggingService != null) { Iterator<DadesEspecifiques> it = llistaResultat.iterator(); while (it.hasNext()) { DadesEspecifiques object = it.next(); loggingService.getLog(this.getClass()).info(object.getDadesXML()); } } } catch (WrappedCheckedException e) { ExceptionDetails details = e.getExceptionDetails(); if (details != null) { if (loggingService != null) { loggingService.getLog(this.getClass()).error(details.getErrorMessage()); } } } catch (Exception e) { if (loggingService != null) { loggingService.getLog(this.getClass()).error(e.getMessage()); } } finally { SSLConfiguration.resetSSL(); } } Cal destacar que l'identificador de la petició ha de ser únic, per aquest motiu es concatena un prefix de text qualsevol amb el timestamp del sistema. Per a més informació respecte l'especificació tècnica i funcional podeu contactar amb l'OT PICA. En aquest exemple, els mètodes privats crearFuncionari() i crearTitular() (creats simplement per aquest test) s'encarreguen de setejar les propietats del funcionari que fa la petició i titular sobre el que es fa la petició respectivament. El mètode també privat createDadesEspecifiques() conté una llista de les sol.licituds, en format XML, que s'enviaran dins la petició. Tot seguit mostrem un exemple del format que han de seguir les dades específiques (que depen del producte/modalitat que es vol consumir): private List<DadesEspecifiques> createDadesEspecifiques() { List<DadesEspecifiques> datosEspecificosXML = new ArrayList<DadesEspecifiques>( ); StringBuffer sb = new StringBuffer("<ns1:request xmlns:ns1=\"http://www.gencat.net/tfn\">" ); sb.append( "<ns1:simpleparam name=\"NUMTIT\">83746573</ns1:simpleparam>" ); sb.append( "<ns1:simpleparam name=\"NUMNIF\">111111111H</ns1:simpleparam>" ); sb.append( "</ns1:request>" ); DadesEspecifiques dades = new DadesEspecifiques(); dades.setIdSolicitud("1"); dades.setDadesXML(sb.toString()); datosEspecificosXML.add(dades); return datosEspecificosXML; } Dins una petició (llista de dades específiques) es poden incloure diverses sol- licituds, els identificadors de les quals han de ser únics dins una mateixa petició. Si volguéssim afegir una altra sol- licitud en l'exemple, només caldria instanciar un nou objecte DadesEspecifiques, amb IdSolicitud="2", un nou StringBuffer amb les dades i afegirlo a la llista datosEspecificosXML. Integració amb Altres ServeisIntegració amb el Servei d'InternacionalitzacióEn els fitxers de configuració es defineixen claus que permeten especificar quins missatges retornar en cas errors. Per a poder traduir aquestes claus és necessari especificar que el connector usarà el Servei d'Internacionalització (veure Configuració). |